﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;

namespace Zinnia.Lite.Core.Imp
{
    /// <summary>
    /// 本地缓存
    /// </summary>
    public class LocalCacheService : ICacheService
    {
        protected ObjectCache LocalCache => MemoryCache.Default;
        public void Add<T>(T obj, string key)
        {
            if (obj == null)
                return;
            var policy = new CacheItemPolicy();
            //永久缓存
            policy.Priority = CacheItemPriority.NotRemovable;
            LocalCache.Add(new CacheItem(key, obj), policy);
        }

        public void Add<T>(T obj, string key, int expireSeconds)
        {
            if (obj == null)
                return;
            var policy = new CacheItemPolicy();
            policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromSeconds(expireSeconds);
            LocalCache.Add(new CacheItem(key, obj), policy);
        }

        public T GetCacheOjbect<T>(string key)
        {
            return (T)LocalCache[key];
        }

        public void RemoveCache(params string[] key)
        {
            if (!key.Any()) return;
            foreach (var k in key)
            {
                LocalCache.Remove(k);
            }
        }
    }
    /// <summary>
    /// 本地缓存依赖
    /// </summary>
    public class LocalDependencyCacheService : LocalCacheService, IDependencyCacheService
    {
        public void Add<T>(T obj, string key, string cacheDependencyKey)
        {
            if (obj != null)
            {
                //1、新建一个CacheItemPolicy对象，该对象用于声明配置对象在缓存中的处理策略
                CacheItemPolicy policy = new CacheItemPolicy();

                //2、因为配置文件一直需要读取，所以在此设置缓存优先级为不应删除
                // 实际情况请酌情考虑，同时可以设置AbsoluteExpiration属性指定过期时间
                policy.Priority = CacheItemPriority.NotRemovable;

                //3、将词典内容添加到缓存，传入 缓存Key、配置对象、对象策略
                // Set方法首先会检查Key是否在缓存中存在，如果存在，更新value，不存在则创建新的
                // 这里先加入缓存再加监视的原因是：在缓存加入时，也会触发监视事件，会导致出错。
                LocalCache.Set(key, obj, policy);

                //4、监视文件需要传入一个IList对象，所以即便只有一个文件也需要新建List对象
                List<string> filePaths = new List<string>() { cacheDependencyKey };

                //5、新建一个文件监视器对象，添加对资源文件的监视
                HostFileChangeMonitor monitor = new HostFileChangeMonitor(filePaths);

                //6、调用监视器的NotifyOnChanged方法传入发生改变时的回调方法
                monitor.NotifyOnChanged(new OnChangedCallback((o) =>
                {
                    LocalCache.Remove(key);
                }));
                //7、为配置对象的缓存策略加入监视器
                policy.ChangeMonitors.Add(monitor);
            }
        }
    }
}
